/*******************************************************************************
 * Copyright (c) 2010, 2018 TU Vienna/ACIN
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    Martin Melik Merkumians, Alois Zoitl,
 *      - initial implementation and rework communication infrastructure
 *    Martin Melik Merkumians - updates naming
 *******************************************************************************/
#ifndef FORTEITERATOR_H_
#define FORTEITERATOR_H_

/*! \ingroup CORE\brief FORTE implementation of a Singly Linked List Iterator
 */

/*!\brief Iterator class of the Singly linked list
 *
 * This is the iterator class of this singly linked list, with minimum functionality needed for read and write access.
 * It's nested in the singly linked list template class for reuse
 *
 * T ... Data Type
 * C ... Node Class i.e. CSinglyLinkedListNode
 */

template<typename T, typename Container>
class CIterator {
  public:
    explicit CIterator(Container *paNode) : mCurrentPosition(paNode) {
    }

    ~CIterator() = default;

    /*!\brief returns the pointer of the current node element
     */

    Container *getPosition() const {
      return mCurrentPosition;
    }

    /*!\brief moves iterator to the next element
     */
    CIterator &operator++() {
      mCurrentPosition = mCurrentPosition->getNext();
      return *this;
    }

    /*!\brief returns reference to contained object
     *
     * \return reference of the contained object of type T
     */
    T &operator*() {
      return mCurrentPosition->getData();
    }

    /*!\brief const version of dereference operator for const iterators
     */
    const T &operator*() const {
      return mCurrentPosition->getData();
    }

    /*!\brief Returns a pointer to the contained object
     * \return A Pointer to the contained object of type T
     */
    T *operator->() {
      return &(**this);
    }

    /*!\brief equality operator for the iterator
     *
     * \return true if position of iterators match, false if otherwise
     */
    bool operator==(CIterator const &rhs) const {
      return mCurrentPosition == rhs.mCurrentPosition;
    }

    /*!\brief inequality operator of the iterator
     *
     * \return false if positions of the iterators match, true if otherwise
     */
    bool operator!=(CIterator const &rhs) const {
      return !(*this == rhs);
    }

    CIterator() = delete;

  private:
    Container *mCurrentPosition;
};

template<typename T, typename Container>
// cppcheck-suppress noConstructor
class CIterator<T *, Container> {
  public:
    CIterator(Container *paNode) : mCurrentPosition(paNode) {
    }

    ~CIterator() = default;

    /*!\brief returns the pointer of the current node element
     */

    Container *getPosition() const {
      return mCurrentPosition;
    }

    /*!\brief moves iterator to the next element
     */
    CIterator &operator++() {
      mCurrentPosition = mCurrentPosition->getNext();
      return *this;
    }

    /*!\brief returns reference to contained object
     *
     * \return reference of the contained object of type T
     */
    T *operator*() {
      return static_cast<T *>(mCurrentPosition->getData());
    }

    /*!\brief const version of dereference operator for const iterators
     */
    const T *operator*() const {
      return static_cast<T *>(mCurrentPosition->getData());
    }

    /*!\brief Returns a pointer to the contained object
     * \return A Pointer to the contained object of type T
     */
    T *operator->() {
      return static_cast<T *>(mCurrentPosition->getData());
    }

    /*!\brief equality operator for the iterator
     *
     * \return true if position of iterators match, false if otherwise
     */
    bool operator==(CIterator const &rhs) const {
      return mCurrentPosition == rhs.mCurrentPosition;
    }

    /*!\brief inequality operator of the iterator
     *
     * \return false if positions of the iterators match, true if otherwise
     */
    bool operator!=(CIterator const &rhs) const {
      return !(*this == rhs);
    }

    CIterator() = delete;

  private:
    Container *mCurrentPosition;
};

#endif /* FORTEITERATOR_H_ */
